package ex05.pyrmont.core;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sky.JULLog.MyLogger;
import org.apache.catalina.Context;
import org.apache.catalina.Contained;
import org.apache.catalina.Container;
import org.apache.catalina.HttpRequest;
import org.apache.catalina.Request;
import org.apache.catalina.Response;
import org.apache.catalina.Valve;
import org.apache.catalina.ValveContext;
import org.apache.catalina.Wrapper;

/**
 * context 级别的 阀 ; 这个 valve 作为 {@link SimplePipelineV5}  的 basic ; 最终调用的就是这个;
 * 就是 这个类实现了 从 URL 到 servlet 的映射;
 * */
public class SimpleContextValveV5 implements Valve, Contained {


    private Logger log = MyLogger.getLogger(SimpleContextValveV5.class);

    protected Container container;

    public void invoke(Request request, Response response, ValveContext valveContext) throws IOException, ServletException {
        // Validate the request and response object types  验证请求和响应对象类型
        if (!(request.getRequest() instanceof HttpServletRequest) ||!(response.getResponse() instanceof HttpServletResponse)) {
            return;     // NOTE - Not much else we can do generically
        }

        // Disallow any direct access to resources under WEB-INF or META-INF
        HttpServletRequest httpServletRequest = (HttpServletRequest) request.getRequest();
        String contextPath = httpServletRequest.getContextPath();
        String requestURI = ((HttpRequest) request).getDecodedRequestURI();
        String relativeURI = requestURI.substring(contextPath.length()).toUpperCase();

        Context context = (Context) getContainer();
        // Select the Wrapper to be used for this Request ;    让  wrapper 把 URL  映射到  servlet
        Wrapper wrapper = null;
        try {
            wrapper = (Wrapper) context.map(request, true);  //mark  映射 servlet
        } catch (IllegalArgumentException e) {
            log.severe(e.getMessage());
            badRequest(requestURI, (HttpServletResponse) response.getResponse());
            return;
        }
        if (wrapper == null) {
            notFound(requestURI, (HttpServletResponse) response.getResponse());
            return;
        }
        // Ask this Wrapper to process this Request
        response.setContext(context);
        wrapper.invoke(request, response);
    }

    public String getInfo() {
        return null;
    }

    public Container getContainer() {
        return container;
    }

    public void setContainer(Container container) {
        this.container = container;
    }

    private void badRequest(String requestURI, HttpServletResponse response) {
        try {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, requestURI);
        } catch (IllegalStateException | IOException e) {
            log.severe(e.getMessage());
        }
    }

    private void notFound(String requestURI, HttpServletResponse response) {
        try {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, requestURI);
        } catch (IllegalStateException | IOException e) {
            log.severe(e.getMessage());
        }
    }

}
